import org.springframework.web.servlet.support.RequestContextUtils as RCU;
import java.text.DateFormat

class LxhTagLib
{

	/**
	 * Creates next/previous links to support pagination for the current controller
	 *
	 * <g:lxhPaginate total="${Account.count()}" action="list"/>
	 */
	def lxhPaginate = 
	{ 
		attrs ->
		def writer = out
        if(attrs.total == null)
            throwTagError("Tag [paginate] is missing required attribute [total]")

		def messageSource = grailsAttributes.getApplicationContext().getBean("messageSource")
		def locale = RCU.getLocale(request)

		def total = attrs.total.toInteger()
		def action = (attrs.action ? attrs.action : (params.action ? params.action : "list"))
		def offset = params.offset?.toInteger()
		def max = params.max?.toInteger()
		def maxsteps = (attrs.maxsteps ? attrs.maxsteps.toInteger() : 10)

		if(!offset) offset = (attrs.offset ? attrs.offset.toInteger() : 0)
		if(!max) max = (attrs.max ? attrs.max.toInteger() : 10)

		def linkParams = [offset:offset - max, max:max]
		if(params.sort) linkParams.sort = params.sort
		if(params.order) linkParams.order = params.order
		if(attrs.params) linkParams.putAll(attrs.params)

		def linkTagAttrs = [action:action]
		if(attrs.controller) {
			linkTagAttrs.controller = attrs.controller
		}
		if(attrs.id!=null) {
			linkTagAttrs.id = attrs.id
		}
		linkTagAttrs.params = linkParams

		// determine paging variables
		def steps = maxsteps > 0
		int currentstep = (offset / max) + 1
		int firststep = 1
		int laststep = Math.round(Math.ceil(total / max))

		// display previous link when not on firststep
		if(currentstep > firststep) {
			linkTagAttrs.class = 'prevLink'
			writer << link(linkTagAttrs.clone()) {
				(attrs.prev ? attrs.prev : messageSource.getMessage('paginate.prev', null, messageSource.getMessage('default.paginate.prev', null, 'Previous', locale), locale))
			 }
		}

		// display steps when steps are enabled and laststep is not firststep
		if(steps && laststep > firststep) {
			linkTagAttrs.class = 'step'

			// determine begin and endstep paging variables
			int beginstep = currentstep - Math.round(maxsteps / 2) + (maxsteps % 2)
			int endstep = currentstep + Math.round(maxsteps / 2) - 1

			if(beginstep < firststep) {
				beginstep = firststep
				endstep = maxsteps
			}
			if(endstep > laststep) {
				beginstep = laststep - maxsteps + 1
				if(beginstep < firststep) {
					beginstep = firststep
				}
				endstep = laststep
			}

			// display firststep link when beginstep is not firststep
			if(beginstep > firststep) {
				linkParams.offset = 0
				writer << link(linkTagAttrs.clone()) {firststep.toString()}
				writer << '<span class="step">..</span>'
			}

			// display paginate steps
			(beginstep..endstep).each { i ->
				if(currentstep == i) {
					writer << "<span class=\"currentStep\">${i}</span>"
				}
				else {
					linkParams.offset = (i - 1) * max
					writer << link(linkTagAttrs.clone()) {i.toString()}
				}
			}

			// display laststep link when endstep is not laststep
			if(endstep < laststep) {
				writer << '<span class="step">..</span>'
				linkParams.offset = (laststep -1) * max
				writer << link(linkTagAttrs.clone()) { laststep.toString() }
			}
		}

		// display next link when not on laststep
		if(currentstep < laststep) {
			linkTagAttrs.class = 'nextLink'
			linkParams.offset = offset + max
			writer << link(linkTagAttrs.clone()) {
				(attrs.next ? attrs.next : messageSource.getMessage('paginate.next', null, messageSource.getMessage('default.paginate.next', null, 'Next', locale), locale))
			}
		}
		
		writer << "<span class='step'>共${total}条</span>"

	}
	

		/**
		 * Examples:
		 * <g:lxhSortCol property="title" title="Title" />
		 * <g:lxhSortCol property="title" title="Title" style="width: 200px" />
		 * <g:lxhSortCol property="title" titleKey="book.title" />	 
		 * <g:lxhSortCol property="releaseDate" defaultOrder="desc" title="Release Date" />
		 * <g:lxhSortCol property="releaseDate" defaultOrder="desc" title="Release Date" titleKey="book.releaseDate" />
		 */	 
		def lxhSortCol = { attrs ->

			if(!attrs.property)
				throwTagError("Tag [sortableColumn] is missing required attribute [property]") 
			
			if(!attrs.title && !attrs.titleKey)
				throwTagError("Tag [sortableColumn] is missing required attribute [title] or [titleKey]")

			def property = attrs.remove("property")
			def action = attrs.action ? attrs.remove("action") : "list"
			
			def defaultOrder = attrs.remove("defaultOrder")
			if(defaultOrder != "desc") defaultOrder = "asc"

			// current sorting property and order
			def sort = params.sort
			def order = params.order

			// add sorting property and params to link params
			def linkParams = [sort:property]
			if(attrs.params) linkParams.putAll(attrs.params)
			
			// determine and add sorting order for this column to link params
			attrs.class = "sortable"
			if(property == sort) {
				attrs.class = attrs.class + " sorted " + order
				if(order == "asc") {
					linkParams.order = "desc"
				}
				else {
					linkParams.order = "asc"
				}
			}
			else {
				linkParams.order = defaultOrder
			}
			
			linkParams.nametj = params.nametj;

			// determine column title
			def title = attrs.remove("title")
			def titleKey = attrs.remove("titleKey")
			if(titleKey) {
				if(!title) title = titleKey
				def messageSource = grailsAttributes.getApplicationContext().getBean("messageSource")
				def locale = RCU.getLocale(request)
				title = messageSource.getMessage(titleKey, null, title, locale)
			}

			out << "<td "
			// process remaining attributes
			attrs.each { k, v ->
				out << "${k}=\"${v.encodeAsHTML()}\" "
			}

			out << " background=\"${createLinkTo(dir:'imagesmain',file:'grayListTableBg.gif')}\" "
			out << ">${link(action:action, params:linkParams) { title }}</td>"
		}

		 
		 
	/**
	* A simple date picker that renders a date as selects
	* eg. <g:lxhDatePicker name="myDate" value="${new Date()}" />
	*/
	def lxhDatePicker = 
	{
	    attrs ->
	
	    def xdefault = attrs['default']
	    if (xdefault == null) 
	    {
	        xdefault = new Date()
	    } else if (xdefault.toString() != 'none')
	    {
	        if (xdefault instanceof String)
	        {
	            xdefault = DateFormat.getInstance().parse(xdefault)
	        }else if(!(xdefault instanceof Date))
	        {
	            throwTagError("Tag [datePicker] requires the default date to be a parseable String or a Date")
	        }
	    } else 
	    {
	        xdefault = null
	    }
	
	    def value = attrs['value']
	    if (value.toString() == 'none') 
	    {
	        value = null
	    } else if (!value) 
	    {
	        value = xdefault
	    }
	    def name = attrs['name']
	    def id = attrs['id'] ? attrs['id'] : name
	
	    def noSelection = attrs['noSelection']
	    if (noSelection != null)
	    {
	        noSelection = noSelection.entrySet().iterator().next()
	    }
	
	    def years = attrs['years']
	
	    final PRECISION_RANKINGS = ["year": 0, "month": 10, "day": 20, "hour": 30, "minute": 40]
	    def precision = (attrs['precision'] ? PRECISION_RANKINGS[attrs['precision']] :
			(grailsApplication.config.grails.tags.datePicker.default.precision ?
				PRECISION_RANKINGS["${grailsApplication.config.grails.tags.datePicker.default.precision}"] :
				PRECISION_RANKINGS["minute"]))
	
	    def day
	    def month
	    def year
	    def hour
	    def minute
	    def dfs = new java.text.DateFormatSymbols(RCU.getLocale(request))
	
	    def c = null
	    if (value instanceof Calendar) 
	    {
	        c = value
	    }
	    else if (value != null) 
	    {
	        c = new GregorianCalendar();
	        c.setTime(value)
	    }
	
	    if (c != null) 
	    {
	        day = c.get(GregorianCalendar.DAY_OF_MONTH)
	        month = c.get(GregorianCalendar.MONTH)
	        year = c.get(GregorianCalendar.YEAR)
	        hour = c.get(GregorianCalendar.HOUR_OF_DAY)
	        minute = c.get(GregorianCalendar.MINUTE)
	    }
	
	    if (years == null) 
	    {
	        def tempyear
	        if (year == null) {
	            // If no year, we need to get current year to setup a default range... ugly
	            def tempc = new GregorianCalendar()
	            tempc.setTime(new Date())
	            tempyear = tempc.get(GregorianCalendar.YEAR)
	        } else {
	            tempyear = year
	        }
	        years = (tempyear - 100)..(tempyear + 100)
	    }
	
	    out << "<input type=\"hidden\" name=\"${name}\" value=\"struct\" />"

	    // create year select
	    if (precision >= PRECISION_RANKINGS["year"]) 
	    {
	        out.println "<select name=\"${name}_year\" id=\"${id}_year\">"
	
	        if (noSelection) {
	            lxhRenderNoSelectionOption(noSelection.key, noSelection.value, '')
	            out.println()
	        }
	
	        for (i in years) {
	            out.println "<option value=\"${i}\""
	            if (i == year) {
	                out.println " selected=\"selected\""
	            }
	            out.println ">${i}</option>"
	        }
	        out.println '</select>'
	    }	    
	
	    // create month select
	    if (precision >= PRECISION_RANKINGS["month"]) 
	    {
	        out.println "<select name=\"${name}_month\" id=\"${id}_month\">"
	
	        if (noSelection) {
	            lxhRenderNoSelectionOption(noSelection.key, noSelection.value, '')
	            out.println()
	        }
	
	        dfs.months.eachWithIndex {m, i ->
	            if (m) {
	                def monthIndex = i + 1
	                out << "<option value=\"${monthIndex}\""
	                if (month == i) out << " selected=\"selected\""
	                out << '>'
	                //out << m
	                out << monthIndex
	                out.println '</option>'
	            }
	        }
	        out.println '</select>'
	    }
	
	    // create day select
	    if (precision >= PRECISION_RANKINGS["day"]) 
	    {
	        out.println "<select name=\"${name}_day\" id=\"${id}_day\">"
	
	        if (noSelection) {
	            lxhRenderNoSelectionOption(noSelection.key, noSelection.value, '')
	            out.println()
	        }
	
	        for (i in 1..31) {
	            out.println "<option value=\"${i}\""
	            if (i == day) {
	                out.println " selected=\"selected\""
	            }
	            out.println ">${i}</option>"
	        }
	        out.println '</select>&nbsp;&nbsp;'
	    }
	
	    // do hour select
	    if (precision >= PRECISION_RANKINGS["hour"]) 
	    {
	        out.println "<select name=\"${name}_hour\" id=\"${id}_hour\">"
	
	        if (noSelection) {
	            lxhRenderNoSelectionOption(noSelection.key, noSelection.value, '')
	            out.println()
	        }
	
	        for (i in 0..23) {
	            def h = '' + i
	            if (i < 10) h = '0' + h
	            out << "<option value=\"${h}\" "
	            if (hour == h.toInteger()) out << "selected=\"selected\""
	            out << '>' << h << '</option>'
	            out.println()
	        }
	        out.println '</select> :'
	
	        // If we're rendering the hour, but not the minutes, then display the minutes as 00 in read-only format
	        if (precision < PRECISION_RANKINGS["minute"]) {
	            out.println '00'
	        }
	    }
	
	    // do minute select
	    if (precision >= PRECISION_RANKINGS["minute"]) 
	    {
	        out.println "<select name=\"${name}_minute\" id=\"${id}_minute\">"
	
	        if (noSelection) {
	            lxhRenderNoSelectionOption(noSelection.key, noSelection.value, '')
	            out.println()
	        }
	
	        for (i in 0..59) {
	            def m = '' + i
	            if (i < 10) m = '0' + m
	            out << "<option value=\"${m}\" "
	            if (minute == m.toInteger()) out << "selected=\"selected\""
	            out << '>' << m << '</option>'
	            out.println()
	        }
	        out.println '</select>'
	    }
	    
	    
	}
    
    def lxhRenderNoSelectionOption = 
    {
	    noSelectionKey, noSelectionValue, value ->
	    // If a label for the '--Please choose--' first item is supplied, write it out
	    out << '<option value="' << (noSelectionKey == null ? "" : noSelectionKey) << '"'
	    if (noSelectionKey.equals(value)) 
	    {
	        out << ' selected="selected" '
	    }
	    out << '>' << noSelectionValue.encodeAsHTML() << '</option>'
	}
    

    
}